package cn.wit.summit.chwan.tools.downloadtool;

import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;

import cn.wit.summit.chwan.models.db.DownLoadTaskTable;
import cn.wit.summit.chwan.models.dbmanager.DownloadTaskManager;
import cn.wit.summit.chwan.models.event.DownloadEvent;
import cn.wit.summit.chwan.task.IZIPThread;
import cn.wit.summit.chwan.task.UNAndroidZIPThread;
import cn.wit.summit.chwan.utils.LogUtils;
import cn.wit.summit.chwan.utils.StringUtils;

import org.greenrobot.eventbus.EventBus;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * Created by Alan on 2018/4/4.
 */

public class DownloadFactory {

    private static DownloadFactory factory;
    private int taskSize = 3;//同时下载数量

    private DownloadListener downloadListener = null;

    private int handlerWhat = 1000;
    private String handlerKey = "data";

    private Map<String, DownloadTask> tasks = new ConcurrentHashMap<>(0);
    private ThreadPoolExecutor executor = new ThreadPoolExecutor(taskSize, taskSize, 0L
            , TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
    private static Map<String, Runnable> zipTasks = new ConcurrentHashMap<String, Runnable>(0);
    private static ThreadPoolExecutor zipExec = new ThreadPoolExecutor(1, 1, 500, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());

    private DownloadFactory() {
    }

    public static DownloadFactory get() {
        if (factory == null){
        factory = new DownloadFactory();
            LogUtils.e("DownloadTask>> " + "new DownloadFatory");
        }
        return factory;
    }

    public void upZipThread(Context context, DownLoadTaskTable downloadTask) {

        DownloadEvent downloadEvent = new DownloadEvent(downloadTask.getDownloadUrl()
                , DownLoadStatusConfig.UNZIP, 0, "0", downloadTask.getGameId());
        EventBus.getDefault().post(downloadEvent);
        IZIPThread zipRunnable = (IZIPThread) zipTasks.get(downloadTask.getGameId());
        if (zipRunnable == null || !zipRunnable.isRunning()) {
            Runnable runnable = new UNAndroidZIPThread(downloadTask, context);

            zipTasks.put(downloadTask.getGameId(), runnable);
            zipExec.execute(runnable);
        }
    }


    public void removeZipTask(String id) {
        zipTasks.remove(id);
    }

    @SuppressLint("HandlerLeak")
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == handlerWhat) {
                synchronized (this) {
                    DownloadEvent mDownloadEvent = (DownloadEvent) msg.getData().getSerializable(handlerKey);
                    try {
                        if (mDownloadEvent.status == DownLoadStatusConfig.DOWNLOADING) {
                            DownLoadTaskTable taskTable = DownloadTaskManager.getInstance().findByGameId(mDownloadEvent.gameId);
                            if (taskTable.getDownStatus() != DownLoadStatusConfig.DOWNLOADING) {
                                LogUtils.e("DownStatues  mHandler "+mDownloadEvent.status);
                                DownloadTaskManager.getInstance().updateStatusBygameId(mDownloadEvent.gameId, mDownloadEvent.status);
                            }
                        } else {
                            DownloadTaskManager.getInstance().updateStatusAndSpeedBygameId(mDownloadEvent.gameId, mDownloadEvent.status,mDownloadEvent.speed);

                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    if (downloadListener != null && mDownloadEvent != null) {
                        downloadListener.onChangeStatus(mDownloadEvent);

                        if (mDownloadEvent.getStatus() == DownLoadStatusConfig.DOWNLOAD_FINISH
                                || mDownloadEvent.getStatus() == DownLoadStatusConfig.DOWNLOAD_ERROR
                                || mDownloadEvent.getStatus() == DownLoadStatusConfig.DOWNLOAD_STOP
                                || mDownloadEvent.getStatus() == DownLoadStatusConfig.UNZIP_ERROR) {
                            DownloadTask t = tasks.get(mDownloadEvent.getGameId());
                            if (t != null){
                                t.cancel();
                            }
                            tasks.remove(mDownloadEvent.getGameId());
                            LogUtils.e("DownloadTask>> " + "mHandler remove Status="+mDownloadEvent.getStatus());
                        }
                    }
                }
            }
        }
    };

    public void addTask(DownloadTask task) {
        LogUtils.e("DownloadTask>> " + "addTask");
        if (task == null || StringUtils.isEmpty(task.getDownloadUrl()))
            return;
        if (tasks.get(task.getGameId()) != null) {
            DownloadTask taskDownLoding = tasks.get(task.getGameId());
//            executor.execute(taskDownLoding);
            LogUtils.e("DownloadTask>> " + " hasTask");
            return;
        }
        task.setHandler(mHandler);

        DownloadEvent downloadEvent = new DownloadEvent(task.getDownloadUrl()
                , DownLoadStatusConfig.WAIT, 0, "0", task.getGameId());

        Bundle b = new Bundle();
        b.putSerializable(handlerKey, downloadEvent);

        Message msg = Message.obtain();
        msg.what = handlerWhat;
        msg.setData(b);
        mHandler.sendMessage(msg);
        LogUtils.e("DownloadTask>> " + "execute");
        executor.execute(task);
        synchronized (tasks) {
            tasks.put(task.getGameId(), task);
            LogUtils.e("DownloadTask>> " + "add "+task.getGameId());
        }
    }

    public boolean stopTask(String gameId) {
        LogUtils.e("DownloadTask>> " + "stopTask "+gameId);
        DownloadTask t = tasks.get(gameId);
        if (t != null){
        t.cancel();
        }
        tasks.remove(gameId);
        return t != null;
    }

    public boolean deletTask(String gameId) {
        DownloadTask t = tasks.get(gameId);
        if (t != null){
            t.delet();
        }
        tasks.remove(gameId);
        return t != null;
    }

    public synchronized void stop() {
        try {
            executor.shutdownNow();
            executor.awaitTermination(1L, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            executor = null;
            tasks.clear();
            tasks = null;
        }
    }

    public void setDownloadListener(DownloadListener downloadListener) {
        this.downloadListener = downloadListener;
    }

    public DownloadListener getDownloadListener() {
        return downloadListener;
    }

    public interface DownloadListener {
        void onChangeStatus(DownloadEvent downloadEvent);
    }
}
